package com.nbjtjc.safe.service.know;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.nbjtjc.safe.bean.Result;
import com.nbjtjc.safe.mapper.know.SafeKnowLabelMapper;
import com.nbjtjc.safe.mapper.know.SafeKnowledgeMapper;
import com.nbjtjc.safe.mapper.know.SafeLabelMapper;
import com.nbjtjc.safe.model.know.SafeKnowLabel;
import com.nbjtjc.safe.model.know.SafeKnowledge;
import com.nbjtjc.safe.model.know.SafeLabel;
import com.nbjtjc.safe.util.FileUtil;
import com.nbjtjc.safe.util.MyShiroUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class SafeKnowledgeService {
    @Autowired
    private SafeKnowledgeMapper safeKnowledgeMapper;

    @Autowired
    private SafeKnowLabelMapper safeKnowLabelMapper;

    @Autowired
    private FileUtil fileUtil;

    @Autowired
    private SafeLabelMapper safeLabelMapper;

    @Lazy
    @Autowired
    private SafeLabelService safeLabelService;
    public Result addBatch(MultipartFile multipartFile,int companyId) throws IOException {
        Result result = new Result();
        String fileName = multipartFile.getOriginalFilename();
        File targetFile = new File(fileUtil.getFilePath() + multipartFile.getOriginalFilename());
        if (!targetFile.getParentFile().exists()) {
            targetFile.getParentFile().mkdirs();
        }
        multipartFile.transferTo(targetFile);
        Set<String> routes = new HashSet<>();
        if (fileName.endsWith("xls")) {
            routes = readXls(targetFile,companyId);
        } else if (fileName.endsWith("xlsx")) {
            routes = readXlsx(targetFile,companyId);
        }
        safeLabelService.constructLabel(routes,companyId);
        return result;
    }

    public Set<String> readXls(File excelFile,int companyId) throws IOException {
        InputStream is = new FileInputStream(excelFile);
        // HSSFWorkbook 标识整个excel
        HSSFWorkbook hssfWorkbook = new HSSFWorkbook(is);

        int size = hssfWorkbook.getNumberOfSheets();
        Set<String> labelRelation = new HashSet<>();
        // 循环每一页，并处理当前循环页
        for (int numSheet = 0; numSheet < size; numSheet++) {
            // HSSFSheet 标识某一页
            HSSFSheet hssfSheet = hssfWorkbook.getSheetAt(numSheet);
            if (hssfSheet == null) {
                continue;
            }
            List<SafeKnowledge> safeKnowledges = new ArrayList<>();
            // 处理当前页，循环读取每一行
            for (int rowNum = 3; rowNum <= hssfSheet.getLastRowNum(); rowNum++) {
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.append(hssfSheet.getSheetName());
                // HSSFRow表示行
                HSSFRow hssfRow = hssfSheet.getRow(rowNum);
                int minColIx = hssfRow.getFirstCellNum();
                int maxColIx = hssfRow.getLastCellNum();
                // 遍历改行，获取处理每个cell元素
                SafeKnowledge safeKnowledge = new SafeKnowledge();
                safeKnowledge.setContent(hssfRow.getCell(0).getStringCellValue());
                safeKnowledge.setLevel(hssfRow.getCell(1).getStringCellValue());
                safeKnowledge.setCreateTime(new Date());
                safeKnowledge.setCompanyId(companyId);
                for (int colIx = 2; colIx < maxColIx; colIx++) {
                    // HSSFCell 表示单元格
                    HSSFCell cell = hssfRow.getCell(colIx);
                    stringBuilder.append("-").append(cell.getStringCellValue());
                    safeKnowledge.getLabels().add(cell.getStringCellValue());
                }
                String labelRoute = stringBuilder.toString();
                labelRelation.add(labelRoute);
                safeKnowledges.add(safeKnowledge);
            }
            safeKnowledgeMapper.insertList(safeKnowledges);
            List<SafeKnowLabel> safeKnowLabels = new ArrayList<>();
            safeKnowledges.forEach(safeKnowledge -> {
                if (CollectionUtil.isNotEmpty(safeKnowledge.getLabels())) {
                    safeKnowledge.getLabels().forEach(label -> {

                        safeKnowLabels.add(new SafeKnowLabel(safeKnowledge.getId(), label,companyId));
                    });
                }
            });
            safeKnowLabelMapper.insertList(safeKnowLabels);
        }
        return labelRelation;

    }

    public Set<String> readXlsx(File excelFile,int companyId) throws IOException {
        InputStream is = new FileInputStream(excelFile);
        // HSSFWorkbook 标识整个excel
        XSSFWorkbook xssfWorkbook = new XSSFWorkbook(is);

        int size = xssfWorkbook.getNumberOfSheets();
        Set<String> labelRelation = new HashSet<>();
        // 循环每一页，并处理当前循环页
        for (int numSheet = 0; numSheet < size; numSheet++) {
            // HSSFSheet 标识某一页
            XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(numSheet);
            if (xssfSheet == null) {
                continue;
            }
            List<SafeKnowledge> safeKnowledges = new ArrayList<>();

            // 处理当前页，循环读取每一行
            for (int rowNum = 3; rowNum <= xssfSheet.getLastRowNum(); rowNum++) {
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.append(xssfSheet.getSheetName());
                // HSSFRow表示行
                XSSFRow xssfRow = xssfSheet.getRow(rowNum);
                int minColIx = xssfRow.getFirstCellNum();
                int maxColIx = xssfRow.getLastCellNum();
                // 遍历改行，获取处理每个cell元素
                SafeKnowledge safeKnowledge = new SafeKnowledge();
                safeKnowledge.setContent(xssfRow.getCell(0).getStringCellValue());
                safeKnowledge.setLevel(xssfRow.getCell(1).getStringCellValue());
                safeKnowledge.setCreateTime(new Date());
                safeKnowledge.setCompanyId(companyId);
                safeKnowledge.getLabels().add(xssfSheet.getSheetName());
                for (int colIx = 2; colIx < maxColIx; colIx++) {
                    // HSSFCell 表示单元格
                    XSSFCell cell = xssfRow.getCell(colIx);
                    if(StringUtils.isNotEmpty(cell.getStringCellValue())){
                        stringBuilder.append("-").append(cell.getStringCellValue());
                        safeKnowledge.getLabels().add(cell.getStringCellValue());
                    }
                }
                String labelRoute = stringBuilder.toString();
                labelRelation.add(labelRoute);
                safeKnowledges.add(safeKnowledge);
            }
            safeKnowledgeMapper.insertList(safeKnowledges);
            List<SafeKnowLabel> safeKnowLabels = new ArrayList<>();
            safeKnowledges.forEach(safeKnowledge -> {
                if (CollectionUtil.isNotEmpty(safeKnowledge.getLabels())) {
                    safeKnowledge.getLabels().forEach(label -> {
                        safeKnowLabels.add(new SafeKnowLabel(safeKnowledge.getId(), label,companyId));
                    });
                }
            });
            safeKnowLabelMapper.insertList(safeKnowLabels);
        }
        return labelRelation;
    }

    private List<SafeLabel> buildLabel(SafeLabel safeLabel, HashSet<String> labelSet) {
        List<String> labels = labelSet.stream().collect(Collectors.toList());
        if (ObjectUtil.isNull(safeLabel.getId())) {
            safeLabelMapper.insert(safeLabel);
        }
        List<SafeLabel> safeLabels = new ArrayList<>();
        labels.forEach(label -> {
            safeLabels.add(new SafeLabel(label, safeLabel.getId()));
        });
        safeLabelMapper.insertList(safeLabels);
        return safeLabels;
    }

    @Transactional(rollbackFor = {Throwable.class})
    public Result add(SafeKnowledge safeKnowledge) {
        Result result = new Result();
        if (ObjectUtil.isNull(safeKnowledge) || ObjectUtil.isNull(safeKnowledge.getContent())) {
            result.setFalse("不能为空");
            return result;
        }
        safeKnowledge.setUserId(MyShiroUtils.getSessionUserId());
        safeKnowledge.setCreateTime(new Date());
        int res = safeKnowledgeMapper.insertSelective(safeKnowledge);
        if (res != 1) {
            result.setFalse("插入失败");
            return result;
        }
        addKnowLabel(safeKnowledge);
        safeKnowledge.setUserName(MyShiroUtils.getSessionUserName());
        result.setData(safeKnowledge);
        return result;
    }

    @Transactional(rollbackFor = {Throwable.class})
    public Result update(SafeKnowledge safeKnowledge) {
        Result result = new Result();
        if (ObjectUtil.isNull(safeKnowledge) || ObjectUtil.isNull(safeKnowledge.getId())
                || safeKnowledge.getId().equals(0)) {
            result.setFalse("不能为空");
            return result;
        }
        safeKnowLabelMapper.deleteByKid(safeKnowledge.getId());
        int res = safeKnowledgeMapper.updateByPrimaryKeySelective(safeKnowledge);
        if (res != 1) {
            result.setFalse("更新失败");
            return result;
        }
        addKnowLabel(safeKnowledge);
        result.setData(safeKnowledge);
        return result;
    }

    private void addKnowLabel(SafeKnowledge safeKnowledge) {
        if (CollectionUtil.isNotEmpty(safeKnowledge.getLabels())) {
            safeKnowledge.setLabels(safeKnowledge.getLabels()
                    .stream().distinct().collect(Collectors.toList()));//去重
            List<SafeKnowLabel> safeKnowLabels = new ArrayList<>();
            safeKnowledge.getLabels().forEach(label -> {
                SafeKnowLabel safeKnowLabel = new SafeKnowLabel();
                safeKnowLabel.setLabel(label);
                safeKnowLabel.setContent(safeKnowledge.getContent());
                safeKnowLabel.setKnowId(safeKnowledge.getId());
                safeKnowLabels.add(safeKnowLabel);
            });
            safeKnowLabelMapper.insertList(safeKnowLabels);
        }
    }

    @Transactional(rollbackFor = {Throwable.class})
    public Result delete(int id) {
        Result result = new Result();
        if (id <= 0) {
            result.setFalse("删除的id不能为小于0的数字");
            return result;
        }
        int res = safeKnowledgeMapper.deleteByPrimaryKey(id);
        if (res != 1) {
            result.setFalse("删除失败");
        }
        return result;
    }

    public Result find(SafeKnowLabel safeKnowLabel) {
        Result result = new Result();
        if (CollectionUtil.isNotEmpty(safeKnowLabel.getLabels())) {
            result.setData(searchByLabels(safeKnowLabel));
        } else {
            SafeKnowledge safeKnowledge = new SafeKnowledge();
            safeKnowledge.setContent(safeKnowLabel.getContent());
            safeKnowledge.setCompanyId(safeKnowLabel.getCompanyId());
            PageHelper.startPage(safeKnowLabel.getPageCurrent(), safeKnowLabel.getPageSize());
            List<SafeKnowledge> safeKnowledges = safeKnowledgeMapper.search(safeKnowledge, null);
            result.setData(new PageInfo<>(safeKnowledges));
        }
        return result;
    }

    private PageInfo searchByLabels(SafeKnowLabel safeKnowLabel) {
        List<Integer> validKnowIds = searchValidKnowIds(safeKnowLabel.getLabels());
        if (validKnowIds.size() == 0) {
            return new PageInfo<>(new ArrayList<SafeKnowledge>());
        }
        SafeKnowledge safeKnowledge = new SafeKnowledge();
        safeKnowledge.setContent(safeKnowLabel.getContent());
        safeKnowledge.setCompanyId(safeKnowLabel.getCompanyId());
        PageHelper.startPage(safeKnowLabel.getPageCurrent(), safeKnowLabel.getPageSize());
        List<SafeKnowledge> safeKnowledges = safeKnowledgeMapper.search(safeKnowledge, validKnowIds);
        return new PageInfo<>(safeKnowledges);
    }

    /**
     * 当知识点都含有 labels中的标签时，返回这些知识点的id
     *
     * @param labels 知识点标签
     * @return
     */
    public List<Integer> searchValidKnowIds(List<String> labels) {
        SafeKnowLabel safeKnowLabel = new SafeKnowLabel();
        HashMap<Integer, Integer> knowMap = new HashMap<>();
        labels.forEach(label -> {
            safeKnowLabel.setLabel(label);
            List<SafeKnowLabel> safeKnowLabels = safeKnowLabelMapper.search(safeKnowLabel);
            if (CollectionUtil.isNotEmpty(safeKnowLabels)) {
                safeKnowLabels.forEach(kl -> {
                    if (knowMap.containsKey(kl.getKnowId())) {
                        knowMap.put(kl.getKnowId(), knowMap.get(kl.getKnowId()) + 1);
                    } else {
                        knowMap.put(kl.getKnowId(), 1);
                    }
                });
            }
        });
        List<Integer> validKnowIds = new ArrayList<>();
        knowMap.entrySet().forEach(entry -> {
            if (entry.getValue() >= labels.size()) {
                validKnowIds.add(entry.getKey());
            }
        });
        return validKnowIds;
    }

    /**
     * 给知识点加标签
     *
     * @return
     */
    @Transactional(rollbackFor = {Throwable.class})
    public Result bindLabelBatch(List<Integer> knowIds, List<String> labels) {
        Result result = new Result();
        if (CollectionUtil.isEmpty(knowIds) || CollectionUtil.isEmpty(labels)) {
            result.setFalse("标签或者选中的知识点为空");
            return result;
        }
        List<SafeKnowLabel> addKnowLabels = new ArrayList<>();
        SafeKnowLabel safeKnowLabel = new SafeKnowLabel();
        safeKnowLabel.setLabels(labels);
        List<SafeKnowLabel> safeKnowLabels = safeKnowLabelMapper.search(safeKnowLabel);
        HashMap<String, HashSet> labelKidsMap = new HashMap<>();
        safeKnowLabels.forEach(knowLabel -> {
            if (labelKidsMap.containsKey(knowLabel.getLabel())) {
                labelKidsMap.get(knowLabel.getLabel()).add(knowLabel.getKnowId());
            } else {
                HashSet<Integer> set = new HashSet<>();
                set.add(knowLabel.getKnowId());
                labelKidsMap.put(knowLabel.getLabel(), set);
            }
        });
        labels.forEach(label -> {
            if (!labelKidsMap.containsKey(label)) {
                knowIds.forEach(knowId -> {
                    SafeKnowLabel addKnowLabel = new SafeKnowLabel(knowId, label);
                    addKnowLabels.add(addKnowLabel);
                });
            } else {
                HashSet<Integer> kIds = labelKidsMap.get(label);
                knowIds.forEach(knowId -> {
                    if (!kIds.contains(knowId)) {
                        addKnowLabels.add(new SafeKnowLabel(knowId, label));
                    }
                });
            }
        });
        if (CollectionUtil.isNotEmpty(addKnowLabels)) {
            safeKnowLabelMapper.insertList(addKnowLabels);
        }
        return result;
    }

    @Transactional(rollbackFor = {Throwable.class})
    public Result deleteLabelBatch(List<Integer> knowIds, List<String> labels) {
        Result result = new Result();
        if (CollectionUtil.isEmpty(labels) || CollectionUtil.isEmpty(knowIds)) {
            result.setFalse("删除的候选项不能为空");
            return result;
        }
        labels.forEach(label -> {
            knowIds.forEach(knowId -> {
                safeKnowLabelMapper.delete(new SafeKnowLabel(knowId, label));
            });
        });
        return result;
    }

    /**
     * 删除知识点上加的标签
     *
     * @param id
     * @return
     */
    public Result deleteKnowLabel(int id) {
        Result result = new Result();
        if (id <= 0) {
            result.setFalse("id不合法");
            return result;
        }
        safeKnowLabelMapper.deleteByPrimaryKey(id);
        return result;
    }

    /**
     * 改造poi默认的toString（）方法如下
     *
     * @param @param  cell
     * @param @return 设定文件
     * @return String    返回类型
     * @throws
     * @Title: getStringVal
     * @Description: 1.对于不熟悉的类型，或者为空则返回""控制串
     * 2.如果是数字，则修改单元格类型为String，然后返回String，这样就保证数字不被格式化了
     */
    public static String getStringVal(HSSFCell cell) {
        switch (cell.getCellType()) {
//            case Cell.CELL_TYPE_BOOLEAN:
//                return cell.getBooleanCellValue() ? "TRUE" : "FALSE";
//            case Cell.CELL_TYPE_FORMULA:
//                return cell.getCellFormula();
//            case Cell.CELL_TYPE_NUMERIC:
//                cell.setCellType(Cell.CELL_TYPE_STRING);
//                return cell.getStringCellValue();
//            case Cell.CELL_TYPE_STRING:
//                return cell.getStringCellValue();
            default:
                return "";
        }
    }


    /**
     * 以公司为单位复制知识点，0表示系统自带知识点，其他表示是公司的id
     *
     * @param fromCompanyId
     * @param toCompanyId
     * @return
     */
    @Transactional
    public boolean copyKnowledge(int fromCompanyId, int toCompanyId) {
        SafeKnowledge safeKnowledge = new SafeKnowledge();
        safeKnowledge.setCompanyId(fromCompanyId);
        SafeKnowLabel safeKnowLabel = new SafeKnowLabel();
        safeKnowLabel.setCompanyId(fromCompanyId);
        List<SafeKnowledge> safeKnowledges = safeKnowledgeMapper.select(safeKnowledge);
        List<SafeKnowledge> insertKnowledges = new ArrayList<>();
        List<SafeKnowLabel> safeKnowLabels = safeKnowLabelMapper.select(safeKnowLabel);
        safeKnowledges.forEach(knowledge -> {
            SafeKnowledge toKnowledge = new SafeKnowledge();
            toKnowledge.setContent(knowledge.getContent());
            toKnowledge.setCompanyId(toCompanyId);
            toKnowledge.setCreateTime(new Date());
            if (ObjectUtil.isNotNull(knowledge.getLevel())) {
                toKnowledge.setLevel(knowledge.getLevel());
            }
            toKnowledge.setFromKnowledgeId(knowledge.getId());
            insertKnowledges.add(toKnowledge);
        });
        HashMap<Integer, List<SafeKnowLabel>> knowLabelMap = new HashMap<>();
        safeKnowLabels.forEach(knowLabel -> {
            if (knowLabelMap.containsKey(knowLabel.getKnowId())) {
                knowLabelMap.get(knowLabel.getKnowId()).add(knowLabel);
            } else {
                List<SafeKnowLabel> knowLabels = new ArrayList<>();
                knowLabels.add(knowLabel);
                knowLabelMap.put(knowLabel.getKnowId(), knowLabels);
            }
        });
        safeKnowledgeMapper.insertList(insertKnowledges);
        //插入知识点标签关系
        List<SafeKnowLabel> insertKnowLabels = new ArrayList<>();
        insertKnowledges.forEach(knowledge -> {
            List<SafeKnowLabel> safeKnowLabelList = knowLabelMap.get(knowledge.getFromKnowledgeId());
            safeKnowLabelList.forEach(fromKnowLabel -> {
                SafeKnowLabel toKnowLabel = new SafeKnowLabel();
                toKnowLabel.setCompanyId(toCompanyId);
                toKnowLabel.setKnowId(knowledge.getId());
                toKnowLabel.setLabel(fromKnowLabel.getLabel());
                insertKnowLabels.add(toKnowLabel);
            });
        });
        safeKnowLabelMapper.insertList(insertKnowLabels);
        return true;
    }
}
